/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package simplemetrosystem.view;

import java.awt.BorderLayout;
import java.awt.Font;
import java.awt.GraphicsEnvironment;
import java.awt.Rectangle;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.Enumeration;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.plaf.FontUIResource;
import org.jvnet.substance.skin.SubstanceOfficeSilver2007LookAndFeel;
import simplemetrosystem.JSplashScreen;
import simplemetrosystem.control.Calculation.CalculManager;
import simplemetrosystem.control.Calculation.ModelManager;
import simplemetrosystem.control.ConfigureManager;
import simplemetrosystem.control.EditCommandManager;
import simplemetrosystem.control.MouseCommandManager;
import simplemetrosystem.control.ElementFactory;
import simplemetrosystem.control.ElementManager;
import simplemetrosystem.model.charlanguage.NameMap;
import simplemetrosystem.view.action.SaveFileActionListener;
import simplemetrosystem.view.bar.EditToolBar;
import simplemetrosystem.view.bar.FloorPanel;
import simplemetrosystem.view.bar.MetroMenuBar;
import simplemetrosystem.view.bar.SystemToolBar;

/**
 *
 * @author Eric Qian
 *
 *
 * 软件主体窗体类，负责软件界面上的各个模块的初始化生成及字体修改
 */
public class MetroFrame extends JFrame implements WindowListener {

    private MetroTabbedPane metroPane;
    private MetroMenuBar menubar;
    private SystemToolBar sysBar;
    private EditToolBar editToolBar;
    private InformationPane infPane;
    private FloorPanel floorBar;
    private AboutFrame aboutFrame;
    private ConfigureFrame configureFrame;
    private NameMap nameMap;
    private NewMapSubject newMapSubject;
    private static ConfigureManager configureManager;

    public static void loadApplication() {
        JFrame.setDefaultLookAndFeelDecorated(true);
        try {
            UIManager.setLookAndFeel(new SubstanceOfficeSilver2007LookAndFeel());
        } catch (Exception e) {
            System.out.println("Substance failed to initialize");
        }
        SwingUtilities.invokeLater(new Runnable() {

            public void run() {
                MetroFrame w = new MetroFrame();
                w.setVisible(true);
            }
        });
    }

    /**
     * 
     */
    public MetroFrame() {
        super();

        try {
            // 给 Splash 屏幕添加一个背景图
            BufferedImage image = ImageIO.read(new File("icon/splash.jpg"));
            // 初始化 Splash 屏幕并显示
            JSplashScreen splash = new JSplashScreen(this, JSplashScreen.SPLASH_MODE, image);
            splash.setVisible(true);
        } catch (IOException ex) {
            Logger.getLogger(MetroFrame.class.getName()).log(Level.SEVERE, null, ex);
        }

        configureManager = ConfigureManager.newInstance();
        nameMap = NameMap.getInstance();
        try {
            BufferedImage icon = ImageIO.read(new File("icon/metro.jpg"));
            this.setIconImage(icon);
        } catch (IOException ex) {
            Logger.getLogger(MetroFrame.class.getName()).log(Level.SEVERE, null, ex);
        }

        this.setTitle(nameMap.getName("MetroEditor"));
        setStyle();
        //用户窗体大小可调
        this.setResizable(true);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        //初始化主题广播器
        newMapSubject = new NewMapSubject();
        //初始化所有命令管理器
        initCommandManagers();
        //模式控制器
        ModelManager.newInstance(this);
        //
        CalculManager.newInstance(this);
        //加载所有窗体组件;
        loadComponents();

        pack();
        Rectangle maxmizedRectangle =
                GraphicsEnvironment.getLocalGraphicsEnvironment().getMaximumWindowBounds();
        this.setMaximizedBounds(maxmizedRectangle);
        //设置窗体默认大小
        this.setBounds(new Rectangle(800, 600));
        //窗体全屏化
        this.setExtendedState(JFrame.MAXIMIZED_BOTH);

    //加载鼠标键盘监听器
    //this.addWindowListener(this);
    //this.addKeyListener(new OpenSaveActionListener(this));
    }

    /**
     * 新建地图画板
     * 前置条件：１．当画板为空时，直接重新新建
     *          ２．当画板已修改时，提示是否保存后新建
     *          ３．当画板为打开文件时，提示是否保存后新建
     */
    public void newMap() {
        if (metroPane != null && !EditCommandManager.getInstance().isClear()) {
            int choice = JOptionPane.showConfirmDialog(this,
                    nameMap.getName("Image has been changed. Save changes?"),
                    "", JOptionPane.YES_NO_CANCEL_OPTION);
            switch (choice) {
                case JOptionPane.YES_OPTION:
                    new SaveFileActionListener(this).save();
                    break;
                case JOptionPane.NO_OPTION:
                    break;
                case JOptionPane.CANCEL_OPTION:
                    // cancel closing the window.
                    this.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
                    break;
            }
        }

        loadMap(null);
    }

    /**
     * 读取地图，新建面板
     * @param path 打开文件路径
     */
    public void loadMap(String path) {
        if (metroPane != null && infPane != null) {
            metroPane.setVisible(false);
            infPane.setVisible(false);
            this.remove(metroPane);
            this.remove(infPane);
        }

        if (path == null) {
            try {
                //初始化元素工厂工厂
                ElementFactory.newInstance();
            } catch (Exception e) {
                e.printStackTrace();
            }
        } else {
            try {
                //初始化元素工厂
                ElementFactory.newInstance(path);
            } catch (Exception ex) {
                ex.printStackTrace();
                JOptionPane.showMessageDialog(this, nameMap.getName("WORRY PATH"),
                        nameMap.getName("WARNING"), JOptionPane.WARNING_MESSAGE);
                ElementFactory.newInstance();
            }
        }
        //初始化撤销管理器
        EditCommandManager.newInstance(ConfigureManager.getInstance().getUndoStep());
        if (path != null) {
            EditCommandManager.getInstance().setNew();
        }

        metroPane = new MetroTabbedPane(this, path);
        infPane = new InformationPane(this);
        this.add(metroPane, BorderLayout.CENTER);
        this.add(infPane, BorderLayout.EAST);

        ElementManager.getInstance().addObserver(metroPane);
        ElementManager.getInstance().addObserver(infPane);

        if (floorBar != null) {
            floorBar.getSizeSlider().setValue(FloorPanel.INITIAL);
        }

        newMapSubject.updateAll();
    }

    /**
     * 初始化地铁画板，面板为单例
     * @return 画板实例
     */
    public MetroTabbedPane getMetroTabbedPane() {
        if (metroPane == null) {
            metroPane = new MetroTabbedPane(this, null);
        }
        return metroPane;
    }

    /**
     * 初始化信息面板,面板为单例
     * @return 面板实例
     */
    public InformationPane getInfPane() {
        if (infPane == null) {
            infPane = new InformationPane(this);
        }
        return infPane;
    }

    /**
     * 
     * @return
     */
    public FloorPanel getFloorBar() {
        if (floorBar == null) {
            floorBar = new FloorPanel(this);
        }
        return floorBar;
    }

    /**
     * 
     * @return
     */
    public EditToolBar getEditToolBar() {
        if (editToolBar == null) {
            editToolBar = new EditToolBar(this);
        }
        return editToolBar;
    }

    /**
     * 
     * @return
     */
    public SystemToolBar getSystemToolBar() {
        if (sysBar == null) {
            sysBar = new SystemToolBar(this);
        }
        return sysBar;
    }

    public MetroMenuBar getMetroMenuBar() {
        if (menubar == null) {
            menubar = new MetroMenuBar(this);
        }
        return menubar;
    }

    /**
     * 显示关于窗口
     */
    public void showConfigureFrame() {
        if (configureFrame == null) {
            configureFrame = new ConfigureFrame(this);
        }
        configureFrame.setVisible(true);
    }

    /**
     * 显示关于窗口
     */
    public void showAboutFrame() {
        if (aboutFrame == null) {
            aboutFrame = new AboutFrame(this);
        }
        aboutFrame.setVisible(true);
    }

    /*
     *使用风格包
     */
    private void setStyle() {
        //字体设置
        initGlobalFontSetting(new Font(null, Font.PLAIN, 14));
    }

    /*
     * 字体初始化
     */
    private void initGlobalFontSetting(Font font) {
        FontUIResource fontRes = new FontUIResource(font);
        for (Enumeration<Object> keys = UIManager.getDefaults().keys(); keys.hasMoreElements();) {
            Object key = keys.nextElement();
            Object value = UIManager.get(key);
            if (value instanceof FontUIResource) {
                UIManager.put(key, fontRes);
            }
        }
    }

    /*
     *读取所有组件
     */
    private void loadComponents() {
        //初始化布局器
        this.setLayout(new BorderLayout());

        newMap();

        //初始化菜单栏

        this.setJMenuBar(this.getMetroMenuBar());
        newMapSubject.addObserver(menubar.getEditMenu());
        //初始化操作工具
        add(getSystemToolBar(), BorderLayout.NORTH);
        newMapSubject.addObserver(sysBar);
        //初始化绘图工具栏   
        add(getEditToolBar(), BorderLayout.WEST);
        //初始化底栏
        add(getFloorBar(), BorderLayout.SOUTH);
    }

    private void initCommandManagers() {
        MouseCommandManager.newInstance(this);
    }

    public void windowOpened(WindowEvent e) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    /*
     *软件关闭时检测画布是否已保存
     */
    public void windowClosing(WindowEvent e) {
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        if (!EditCommandManager.getInstance().isClear()) {
            int choice = JOptionPane.showConfirmDialog(this,
                    nameMap.getName("Image has been changed. Save changes?"),
                    "", JOptionPane.YES_NO_CANCEL_OPTION);
            switch (choice) {
                case JOptionPane.YES_OPTION:
                    new SaveFileActionListener(this).save();
                    break;
                case JOptionPane.NO_OPTION:
                    break;
                case JOptionPane.CANCEL_OPTION:
                    // cancel closing the window.
                    this.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
                    break;
            }
        }
    }

    public void windowClosed(WindowEvent e) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    public void windowIconified(WindowEvent e) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    public void windowDeiconified(WindowEvent e) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    public void windowActivated(WindowEvent e) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    public void windowDeactivated(WindowEvent e) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    /*
     * 软件入口
     */
    public static void main(String[] args) {
        MetroFrame.loadApplication();
    }
}
